package com.mxm.mirai.websocket;


import com.mxm.mirai.dao.BotWebSocketChat;
import com.google.gson.Gson;
import com.mxm.mirai.jwt.JWTUtil;
import net.mamoe.mirai.Bot;
import net.mamoe.mirai.contact.Friend;
import net.mamoe.mirai.message.FriendMessageEvent;
import net.mamoe.mirai.message.data.LightApp;
import net.mamoe.mirai.message.data.MessageUtils;
import net.mamoe.mirai.message.data.ServiceMessage;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.Base64;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Component
@ServerEndpoint("/chat_friend/{qq}/{friend}/{base64}")
public class WebSocketFriendsServer {
    static Log log= LogFactory.getLog(WebSocketFriendsServer.class);
    /**静态变量，用来记录当前在线连接数。应该把它设计成线程安全的。*/
    private static int onlineCount = 0;
    /**concurrent包的线程安全Set，用来存放每个客户端对应的MyWebSocket对象。*/
    private static ConcurrentHashMap<String, WebSocketFriendsServer> webSocketMap = new ConcurrentHashMap<>();
    /**与某个客户端的连接会话，需要通过它来给客户端发送数据*/
    private Session session;
    /**接收userId*/
    private static String qqid=null;
    private static String friendid=null;
    private static String token=null;
    private static BotWebSocketChat webSocketChat = new BotWebSocketChat();
    private static Gson gson = new Gson();
    /**
     * 连接建立成功调用的方法*/
    @OnOpen
    public void onOpen(Session session, @PathParam("qq") String qq,@PathParam("friend") String friend, @PathParam("base64") String base64) {
        try {
            this.token = new String(Base64.getDecoder().decode(base64), "UTF-8");
            String name = JWTUtil.getUsername(token);
            if(JWTUtil.verify(token, name)){
                this.token = name;
            }
        }catch (Exception e){}
        this.session = session;
        this.qqid=qq;
        this.friendid=friend;
        if(webSocketMap.containsKey(qqid)){
            webSocketMap.remove(qqid);
            webSocketMap.put(qqid,this);
            //加入set中
        }else{
            webSocketMap.put(qqid,this);
            //加入set中
            addOnlineCount();
            //在线数加1
        }
        log.info("好友用户连接:"+qqid+",当前在线人数为:" + getOnlineCount());
        try {
            if(token.indexOf("@")!=-1){
            sendMessage("服务连接成功");
            }else {
            sendMessage("服务信息校验失败");
            onClose();
            }
        } catch (IOException e) {
            log.error("好友用户:"+qqid+",网络异常!!!!!!");
        }
    }
    /**
     * 连接关闭调用的方法
     */
    @OnClose
    public void onClose() {
        if(webSocketMap.containsKey(qqid)){
            webSocketMap.remove(qqid);
            //从set中删除
            subOnlineCount();
        }
        log.info("好友用户退出:"+qqid+",当前在线人数为:" + getOnlineCount());
    }
    /**
     * 收到客户端消息后调用的方法
     *
     * @param message 客户端发送过来的消息*/
    @OnMessage
    public void onMessage(@PathParam("qq") String qq,String message, Session session) {
        log.info("好友用户消息:"+qqid+",报文:"+message);
        webSocketChat = gson.fromJson(message, BotWebSocketChat.class);
        try {
            Friend friend = Bot.getInstance(new Long(qqid)).getFriend(new Long(friendid));
            if(webSocketChat.getContent().indexOf("<?xml")!=-1 && webSocketChat.getContent().indexOf("serviceID")!=-1){
                friend.sendMessage(new ServiceMessage(60,webSocketChat.getContent()));//xml消息
            }else if(webSocketChat.getContent().indexOf("{\"app\":\"")!=-1){
                friend.sendMessage(new LightApp(webSocketChat.getContent()));//json消息
            }else {
                friend.sendMessage(webSocketChat.getContent());//文本消息
            }
            log.info("成功发送消息给"+friend.getNick());
        }catch (Exception e){
            log.info("发送失败！");
        }
    }
    /**
     *
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session, Throwable error) {
        log.error("好友用户错误:"+this.qqid+",原因:"+error.getMessage());
        error.printStackTrace();
    }
    /**
     * 实现服务器主动推送
     */
    public void sendMessage(String message) throws IOException {
        this.session.getBasicRemote().sendText(message);
    }
    /**
     * 发送自定义消息
     */
    public static void sendInfo(FriendMessageEvent event){
        if(StringUtils.isNotBlank(qqid)&&webSocketMap.containsKey(qqid)){
            Long qq = event.getBot().getId();
            Long friend= event.getSender().getId();
            String avatar = event.getSender().getAvatarUrl();
            String nick = event.getSender().getNick();
            String msg = event.getMessage().contentToString();
            if (event.getMessage().toString().contains("[mirai:image:")) {
                String text = event.getMessage().toString();
                String url = StringUtils.substringBetween(text, "[mirai:image:", "]");
                msg = event.getBot().queryImageUrl(MessageUtils.newImage(url));
                msg = msgTo(text).replace("[mirai:image:"+url+"]","img["+msg+"]");
            }
            if(qqid.equals(qq.toString())){
                log.info("发送消息到:"+qqid+"，报文:"+msg);
                webSocketChat.setId(friend.toString());
                webSocketChat.setAvatar(avatar.replace("s=640","s=100"));
                webSocketChat.setUsername(nick);
                webSocketChat.setType("kefu");
                webSocketChat.setContent(msg);
                String json = gson.toJson(webSocketChat);
                try {
                    webSocketMap.get(qqid).sendMessage(json);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }else{
            log.error("好友用户"+qqid+",不在线！");
        }
    }

    public static synchronized int getOnlineCount() {
        return onlineCount;
    }

    public static synchronized void addOnlineCount() {
        WebSocketFriendsServer.onlineCount++;
    }

    public static synchronized void subOnlineCount() {
        WebSocketFriendsServer.onlineCount--;
    }
    private static String msgTo(String text){
        String msg="";
        Matcher m = Pattern.compile("\\[mirai:source:(.*?)\\]").matcher(text);
        while (m.find()) {
            msg = text.replace(m.group(0),"");
        }
        return msg;
    }
}
